package com.edgar.thread.ch02;

import java.io.IOException;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicReference;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

import com.edgar.thread.annotation.NotThreadSafe;

/**
 * 缓存在lastFactors中的各个因子的乘积应该等于缓存在lastNumber中的数值。
 * 当一个不变约束涉及多个变量时，变量间不是彼此独立的：某个变量的值会制约其他几个变量的值。 因此，更新一个变量的时候，要在同一原子操作中更新其他几个。
 * 在UnsafeCatchFactorizer中
 * ，无法保证会同时更新lastNumber和lastFactors:当某个线程只修改了一个变量而另外一个还没有开始修改时
 * ，其他线程都会同时获得两个值：当线程A尝试获取两个值的时间里，线程B可能已经修改了它们，线程A过后会观察到Servlet违反了不变约束。
 * 
 * 为了保护状态的一致性，要在单一的原子操作中更新相互关联的状态变量。
 * 
 * @author Edgar Zhang
 * 
 */
@NotThreadSafe
public class UnsafeCachingFactorizer extends HttpServlet {

	private final AtomicReference<BigInteger> lastNumber = new AtomicReference<BigInteger>();
	private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference<BigInteger[]>();

	@Override
	public void service(ServletRequest request, ServletResponse response)
			throws ServletException, IOException {
		BigInteger i = extractFromRequest(request);
		if (i.equals(lastNumber.get())) {
			encodeIntoResponse(response, lastFactors.get());
		} else {
			BigInteger[] factors = factor(i);
			lastNumber.set(i);
			lastFactors.set(factors);
			encodeIntoResponse(response, factors);
		}
	}

	private void encodeIntoResponse(ServletResponse response,
			BigInteger[] factors) {
		// TODO Auto-generated method stub

	}

	private BigInteger[] factor(BigInteger i) {
		// TODO Auto-generated method stub
		return null;
	}

	private BigInteger extractFromRequest(ServletRequest request) {
		// TODO Auto-generated method stub
		return null;
	}
}